#include "stdafx.h"
#include "Heap.h"
#include <stdlib.h>
#include <iostream>
using namespace MEM;
 
 
void stress_test(Heap& mgr)
{
	mgr.Dump();
	std::cout<<"stress test start, 10000000 times random num new and delete"<<std::endl;
	char* pointerArray[100] = {0};
	int pointerIdx = -1;
	size_t newTimes = 0;
	size_t deleteTimes = 0;
	for (unsigned int i = 0; i< 10000000; i++)
	{
		if ((rand() & 1) == 1 && pointerIdx < 100)
		{
			size_t rand_num_to_new =  (size_t)(rand()/(float)RAND_MAX * (mgr.LargestFreeBlock() ));
			if( rand_num_to_new > 0  )
			{
				void* pt = mgr.Mem_new(rand_num_to_new,__FILE__,__LINE__);
				pointerArray[++pointerIdx] = (char*)pt;
				newTimes++;
			}
			else
				i--;
		}
		else
		{
			if(pointerIdx>=0)
			{
				mgr.Mem_delete(pointerArray[pointerIdx--]);
				deleteTimes++;
			}
			else
				i--;
		}

	}
	std::cout<<"new times: "<<newTimes<<std::endl;
	std::cout<<"delete times: "<<deleteTimes<<std::endl;

	std::cout<<"Free all memory"<<std::endl;
	mgr.TotalFreeMem();
	mgr.Dump();
}

int _tmain(int argc, _TCHAR* argv[])
{
	char outerMem[10240];
	Heap mgr = Heap(outerMem,10240);//handle the memory to Mgr
	std::cout<<"pass memory to mgr: 10240"<<std::endl;
 

	//temp test

	std::cout<<"test split and coalesce."<<std::endl;
	std::cout<<"allocate 3 mem blocks and delete them in different order"<<std::endl;
	char* testp1 = reinterpret_cast<char*>( mgr.Mem_new(100,__FILE__,__LINE__) );
	char* testp2 = reinterpret_cast<char*>( mgr.Mem_new(101,__FILE__,__LINE__) );
	char* testp3 = reinterpret_cast<char*>( mgr.Mem_new(102,__FILE__,__LINE__) );
	mgr.Mem_delete(testp2);
	mgr.Mem_delete(testp1);
	mgr.Mem_delete(testp3);

	std::cout<<"new memory p1. 512"<<std::endl;
	char* p1 = reinterpret_cast<char*>( mgr.Mem_new(512,__FILE__,__LINE__) );
	
	std::cout<<"new memory p_s1_dangling: 300."<<std::endl;
	char* p_s1_dangling = reinterpret_cast<char*>( mgr.Mem_new(300,__FILE__,__LINE__) );
	 
	
	std::cout<<"delete memory p_s1_dangling: 300."<<std::endl;
	mgr.Mem_delete(p_s1_dangling);
	
	std::cout<<"check the dangling pointers :p_s1_dangling :";
	bool b_valid = mgr.IsPtrValid(p_s1_dangling);//check the dangling pointer
	std::cout<<(b_valid?"true":"false")<<std::endl;

	std::cout<<"new memory p_s2, this will be used to check the leak: 250."<<std::endl;
	char* p_s2 = reinterpret_cast<char*>( mgr.Mem_new(250,__FILE__,__LINE__) );
	



	std::cout<<"mgr's usage info:"<<std::endl;
	mgr.Dump();//show usage

	std::cout<<"create manager another_mgr."<<std::endl;
	char memheap2[512];
	Heap another_mgr = Heap(memheap2,512);//multiple heaps
	
	std::cout<<"create subHeap in another_mgr."<<std::endl;
	Heap* sub_heap = another_mgr.subHeap(128);
	

	std::cout<<"another_mgr's usage info:"<<std::endl;
	
	sub_heap->Mem_new(30,__FILE__,__LINE__,'ctex');
	sub_heap->Dump('ctex');// usage info

	

	

	
	std::cout<<"get the worst case usage in mgr :";
	size_t wstPtr = mgr.GetWorstCaseUsageMemory();//worst case memory
	std::cout<<wstPtr<<std::endl;

	std::cout<<"verify the memory in mgr."<<std::endl;
	mgr.Verify();
	

	std::cout<<"resource failures test."<<std::endl;
	mgr.Mem_new(123456,__FILE__,__LINE__);//throw an exception!
	
	std::cout<<"delete p1."<<std::endl;
	mgr.Mem_delete(p1);
	

	std::cout<<"test double delete p1."<<std::endl;
	mgr.Mem_delete(p1);

	std::cout<<"---checking memory leak---"<<std::endl;
	mgr.checkLeak();

	std::cout<<"---Free all memory in mgr---"<<std::endl;
	mgr.TotalFreeMem();
	std::cout<<"---checking memory leak---"<<std::endl;
	mgr.checkLeak();

	//delete sub_heap;

	stress_test(mgr);
	
	system("pause");
	return 0;
}

